package it.unibo.imola.parser.visitor.entity;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

public class DefinitionInstruction extends Instruction {

	protected String name;
	protected StatementSequence statementSequence;
	protected Map<String,Class<?>> formalParameters;
	
	public DefinitionInstruction(String name) {
		if(name == null)
			throw new IllegalArgumentException("name == null");
		this.name = name;
		formalParameters = new LinkedHashMap<String, Class<?>>(0);
		statementSequence = new StatementSequence(this);
	}
	
	@Override
	public boolean check(Environment env) throws Exception {
		super.check(env);
		// qui gli sto passando l'env GLOBALE
		GlobalEnvironment gEnv = (GlobalEnvironment)env;
		
		// controllo che non ci siano altre def con lo stesso nome
		if(gEnv.getDefinitions().containsKey(name))
			return false;
		
		// controllo che la sequenza di azioni sia coerente
		if(!statementSequence.check(gEnv))
			return false;
		
		gEnv.definitions.put(name, statementSequence);
		
		return true;
	}
	
	@Override
	public void exec(Environment env) throws Exception {
		super.exec(env);
		
		// in pratica devo modificare l'env (globale) ed inserire un riferimento ad una 
		// qualche sequenza di istruzioni da eseguire (PREVIA setting dei parametri attuali)
		
		GlobalEnvironment gEnv = (GlobalEnvironment)env;
		gEnv.definitions.put(name, statementSequence);
		//statementSequence.exec(env);	// questa roba non deve essere eseguita dalla definition, ma dalla call che chiama la definition
	}

	/**
	 * @return the formalParameters
	 * 
	 * <NOME,TIPO>
	 */
	public Map<String, Class<?>> getFormalParameters() {
		return formalParameters;
	}
	
	public void addStatement(Statement s){
		if(s == null)
			throw new IllegalArgumentException("s == null");
		statementSequence.getStatements().add(s);
	}
	
	public Class<?>[] getFormalParameterTypes() {
		return formalParameters.values().toArray(new Class<?>[0]);
	}

//	public List<Statement> getStatements(Object[] unboxedActualParameters) {
//		// TODO Auto-generated method stub
//		return null;
//	}

	@Override
	public String toString() {
		return ReflectionToStringBuilder.toString(this);
	}

}
